package com.smart.community.property.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.cache.DataScopeInfo;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.property.entity.WaterFee;
import com.smart.community.property.enums.PaymentMethodEnum;
import com.smart.community.property.exception.DataScopeException;
import com.smart.community.property.mapper.WaterFeeMapper;
import com.smart.community.property.service.DataScopeService;
import com.smart.community.property.service.IWaterFeeService;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;

/**
 * 水费服务实现
 * @author Wu.Liang
 * @since 2025-06-26
 * @version 1.0.0
 */
@Slf4j
@Service
public class WaterFeeServiceImpl extends ServiceImpl<WaterFeeMapper, WaterFee> implements IWaterFeeService {

    @Autowired
    private WaterFeeMapper waterFeeMapper;

    @Autowired
    private DataScopeService dataScopeService;

    @Override
    public IPage<WaterFee> getWaterFeePage(Page<WaterFee> page, Long communityId, Integer paymentStatus) throws Exception {
        log.info("分页查询水费账单，社区ID: {}, 支付状态: {}", communityId, paymentStatus);
        
        // 数据权限验证
        DataScopeInfo dataScopeInfo = null;
        try {
            dataScopeInfo = dataScopeService.getCurrentUserDataScope();
        } catch (Exception e) {
            log.warn("获取当前用户数据权限信息失败，可能是Feign接口调用或用户未登录，返回空结果: {}", e.getMessage());
            // 根据Feign接口开发规范，当无法获取用户权限信息时，返回空结果
            page.setRecords(new ArrayList<>());
            page.setTotal(0);
            return page;
        }
        
        if (dataScopeInfo == null || !dataScopeInfo.isPropertyCompanyUser()) {
            log.warn("非物业公司用户或无数据权限，返回空结果");
            page.setRecords(new ArrayList<>());
            page.setTotal(0);
            return page;
        }

        // 如果指定了社区ID，验证权限
        if (communityId != null) {
            Long userId = SecurityUtils.getCurrentUserId();
            try {
                dataScopeService.hasCommunityPermission(userId, communityId);
            } catch (Exception e) {
                log.warn("用户无权访问指定社区，社区ID: {}, 用户ID: {}", communityId, userId);
                page.setRecords(new ArrayList<>());
                page.setTotal(0);
                return page;
            }
        } else {
            // 如果没有指定社区ID，使用用户可访问的社区列表
            List<Long> authorizedCommunityIds = dataScopeInfo.getCommunityIds();
            if (authorizedCommunityIds.isEmpty()) {
                log.warn("用户无数据访问权限，返回空结果");
                page.setRecords(new ArrayList<>());
                page.setTotal(0);
                return page;
            }
            // 暂时使用第一个有权限的社区
            communityId = authorizedCommunityIds.get(0);
        }

        // 计算偏移量
        int offset = (int) ((page.getCurrent() - 1) * page.getSize());
        int limit = (int) page.getSize();
        
        // 查询数据
        int total = waterFeeMapper.countByCommunityAndStatus(communityId, paymentStatus);
        List<WaterFee> records = waterFeeMapper.selectPageByCommunityAndStatus(communityId, paymentStatus, offset, limit);
        
        // 设置分页结果
        page.setRecords(records);
        page.setTotal(total);
        
        log.info("水费账单分页查询完成，总数: {}, 当前页: {}", total, page.getCurrent());
        return page;
    }

    @Override
    public WaterFee getLatestReadingByHouseholdId(Long householdId) {
        log.debug("查询房户最新水表读数，房户ID: {}", householdId);
        return waterFeeMapper.selectLatestReadingByHouseholdId(householdId);
    }

    @Override
    public WaterFee getByHouseholdIdAndBillingPeriod(Long householdId, String billingPeriod) {
        log.debug("查询房户指定期间水费记录，房户ID: {}, 计费期间: {}", householdId, billingPeriod);
        return waterFeeMapper.selectByHouseholdIdAndBillingPeriod(householdId, billingPeriod);
    }

    @Override
    @GlobalTransactional
    public boolean submitWaterMeterReading(Long householdId, BigDecimal reading, LocalDate readingDate) {
        log.info("提交水表读数，房户ID: {}, 表读数: {}, 读数日期: {}", householdId, reading, readingDate);
        
        try {
            // 数据权限验证（通过房户ID获取社区ID）
            WaterFee latestReading = waterFeeMapper.selectLatestReadingByHouseholdId(householdId);
            if (latestReading != null) {
                Long userId = SecurityUtils.getCurrentUserId();
                dataScopeService.hasCommunityPermission(userId, latestReading.getCommunityId());
            }

            // 获取最新的水表读数
            if (latestReading != null && latestReading.getCurrentReading().compareTo(reading) >= 0) {
                throw new BusinessException("新读数不能小于或等于上次读数");
            }

            // 创建新的水费记录
            WaterFee waterFee = new WaterFee();
            waterFee.setHouseholdId(householdId);
            waterFee.setCurrentReading(reading);
            waterFee.setReadingDate(readingDate);
            waterFee.setPaymentStatus(0); // 未支付

            boolean result = waterFeeMapper.insert(waterFee) > 0;
            log.info("水表读数提交完成，房户ID: {}, 结果: {}", householdId, result);
            return result;
        } catch (Exception e) {
            log.warn("提交水表读数失败", e);
            throw new BusinessException("提交水表读数失败");
        }
    }

    @Override
    @GlobalTransactional
    public boolean batchSubmitMeterReading(Long communityId, List<Map<String, Object>> meterReadings) throws Exception {
        log.info("批量提交水表读数，社区ID: {}, 数据条数: {}", communityId, meterReadings.size());
        
        try {
            // 数据权限验证
            Long userId = SecurityUtils.getCurrentUserId();
            dataScopeService.hasCommunityPermission(userId, communityId);
            
            for (Map<String, Object> reading : meterReadings) {
                Long householdId = Long.valueOf(reading.get("householdId").toString());
                BigDecimal currentReading = new BigDecimal(reading.get("reading").toString());
                LocalDate readingDate = LocalDate.parse(reading.get("readingDate").toString());
                
                submitWaterMeterReading(householdId, currentReading, readingDate);
            }
            
            log.info("批量提交水表读数完成，社区ID: {}", communityId);
            return true;
        } catch (Exception e) {
            log.warn("批量提交水表读数失败", e);
            throw new BusinessException("批量提交水表读数失败");
        }
    }

    @Override
    @GlobalTransactional
    public boolean payWaterFee(Long billId, BigDecimal paymentAmount, String paymentMethod, LocalDateTime paymentTime) throws Exception {
        log.info("支付水费，账单ID: {}, 支付金额: {}, 支付方式: {}", billId, paymentAmount, paymentMethod);
        
        try {
            WaterFee fee = waterFeeMapper.selectById(billId);
            if (fee == null) {
                log.warn("水费记录不存在，ID: {}", billId);
                throw new BusinessException("水费记录不存在");
            }

            // 数据权限验证
            Long userId = SecurityUtils.getCurrentUserId();
            dataScopeService.hasCommunityPermission(userId, fee.getCommunityId());

            // 转换支付方式：字符串转换为整数值
            Integer paymentMethodCode = convertPaymentMethodToCode(paymentMethod);
            if (paymentMethodCode == null) {
                throw new BusinessException("不支持的支付方式: " + paymentMethod);
            }
            
            fee.setPaymentAmount(paymentAmount);
            fee.setPaymentMethod(paymentMethodCode);
            fee.setPaymentStatus(1);
            fee.setPaymentTime(paymentTime);
            
            // 修复：同步更新已支付金额和未支付金额
            fee.setPaidAmount(paymentAmount); // 已支付金额设置为支付金额
            fee.setUnpaidAmount(BigDecimal.ZERO); // 未支付金额清零

            boolean result = waterFeeMapper.updateById(fee) > 0;
            log.info("水费支付完成，账单ID: {}, 结果: {}", billId, result);
            return result;
        } catch (Exception e) {
            log.warn("支付水费失败", e);
            throw new BusinessException("支付水费失败");
        }
    }

    @Override
    public int generateWaterFee(Long communityId, String billingPeriod, BigDecimal unitPrice) throws Exception {
        log.info("生成水费账单，社区ID: {}, 计费期间: {}, 单价: {}", communityId, billingPeriod, unitPrice);
        // fee_type=2 水费，已在SQL层强制，无需外部传递
        return waterFeeMapper.batchGenerateWaterFee(communityId, billingPeriod, unitPrice);
    }

    @Override
    public List<WaterFee> getAbnormalUsageRecords(Long communityId, BigDecimal minUsage, BigDecimal maxUsage) throws Exception {
        log.info("查询异常用量记录，社区ID: {}, 最小用量: {}, 最大用量: {}", communityId, minUsage, maxUsage);
        return waterFeeMapper.selectAbnormalUsageRecords(communityId, minUsage, maxUsage);
    }

    @Override
    public List<WaterFee> getUnpaidWaterFeesByUserId(Long userId) throws Exception {
        log.info("查询用户未缴费水费账单，用户ID: {}", userId);
        return waterFeeMapper.selectUnpaidByUserId(userId);
    }

    @Override
    public Map<String, Object> getWaterFeeStatistics(Long communityId, Integer year) throws Exception {
        log.info("获取水费统计信息，社区ID: {}, 年份: {}", communityId, year);
        return waterFeeMapper.selectStatistics(communityId, year);
    }
    
    /**
     * 转换支付方式字符串为整数值
     * 
     * @param paymentMethod 支付方式字符串
     * @return 支付方式整数值，如果不支持则返回null
     */
    private Integer convertPaymentMethodToCode(String paymentMethod) {
        if (paymentMethod == null || paymentMethod.trim().isEmpty()) {
            return null;
        }
        
        PaymentMethodEnum methodEnum = PaymentMethodEnum.fromValue(paymentMethod.trim());
        return methodEnum != null ? methodEnum.getCode() : null;
    }
}
